package com.jhh.pay.center.service.impl;

import com.jhh.pay.center.cfg.caching.Cache;
import com.jhh.pay.center.dao.OrderMapper;
import com.jhh.pay.center.model.Order;
import com.jhh.pay.center.model.OrderType;
import com.jhh.pay.center.search.DocTransformer;
import com.jhh.pay.center.search.Searcher;
import com.jhh.pay.center.search.mapping.DeductMapping;
import com.jhh.pay.center.search.mapping.PayMapping;
import com.jhh.pay.center.service.FlowIdBuilder;
import com.jhh.pay.center.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.concurrent.TimeUnit;

/**
 * @author tangxd
 * @Description: TODO
 * @date 2017/12/6
 */
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private FlowIdBuilder idBuilder;

    @Autowired
    private Searcher<PayMapping> paySearcher;

    @Autowired
    private Searcher<DeductMapping> deductSearcher;

    @Autowired
    private DocTransformer<Order, DeductMapping> deductTransformer;

    @Autowired
    private DocTransformer<Order, PayMapping> payTransformer;

    @Autowired
    private Cache cache;

    private String cacheKey(String id) {
        return String.format("jhh:pay:order:%s", id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(Order order) {
        order.setId(idBuilder.newId(order.getType()));
        boolean ok = orderMapper.insert(order) > 0;
        if (ok) {
            if (!updateIndex(order)) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return false;
            }
        }
        return ok;
    }

    @Override
    public Order get(String id) {
        Order order = cache.get(cacheKey(id), Order.class);
        if (null == order) {
            order = orderMapper.get(id);
            cache.set(cacheKey(id), order, TimeUnit.SECONDS.convert(1, TimeUnit.DAYS));
        }
        return order;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(Order order) {
        boolean ok = orderMapper.update(order) > 0;
        if (ok) {
            if (!updateIndex(order)) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return false;
            }
        }
        return ok;
    }

    private boolean updateIndex(Order order) {
        boolean ok = false;
        try {
            switch (order.getType()) {
                case PAY:
                    PayMapping pm = payTransformer.transform(order);
                    ok = paySearcher.index(pm, true);
                    break;
                case DEDUCT:
                    DeductMapping dm = deductTransformer.transform(order);
                    ok = deductSearcher.index(dm, true);
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return false;
        }
        if (ok) {
            cache.set(cacheKey(order.getId()), order, TimeUnit.SECONDS.convert(1, TimeUnit.DAYS));
        }
        return ok;
    }
}
